import com.alibaba.fastjson.JSONArray;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.opengis.referencing.operation.MathTransform;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class CoordTransformService {
    // web墨卡托坐标系椭球(正球)参数
    private static final double originShift = 2 * Math.PI * 6378137 / 2.0;
    private static final GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

    public double[] transformCoord(File file, String srcCrsCode, String dstCrsCode) throws IOException {
        JSONArray data = new JSONArray();
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line = "";
        while ((line = br.readLine()) != null) {
            String[] lineSegments = line.split(",");
            if (lineSegments.length > 1) {
                double lon = Double.parseDouble(lineSegments[1]);
                double lat = Double.parseDouble(lineSegments[2]);
                double[] xy = this.crsTransform(srcCrsCode, dstCrsCode, lon, lat, true);
                return xy;
            } else {
                return new double[]{0, 0};
            }
        }
        return new double[]{0, 0};
    }

    /**
     * 4326坐标系经纬度转3857坐标系的XY
     *
     * @param lon
     * @param lat
     * @return
     */
    public static double[] lonLat2WebMercator(double lon, double lat) {
        double[] mercator = new double[2];
        double x = lon * originShift / 180.0;
        double y = Math.log(Math.tan((90 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0);
        y = y * originShift / 180;

        mercator[0] = x;
        mercator[1] = y;

        return mercator;
    }

    /**
     * 3857坐标系的XY转4326坐标系经纬度
     *
     * @param x
     * @param y
     * @return
     */
    public static double[] WebMercator2lonLat(double x, double y) {
        double[] lonlat = new double[2];
        double lon = (x / originShift) * 180;
        double lat = (y / originShift) * 180;
        lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0);

        lonlat[0] = lon;
        lonlat[1] = lat;

        return lonlat;
    }

    /**
     * 坐标系转换工具
     *
     * @param srcCrs     原坐标系
     * @param dstCrs     目标坐标系
     * @param x
     * @param y
     * @param allowError 是否允许坐标转换有误差
     * @return
     */
    public static double[] crsTransform(String srcCrs, String dstCrs, double x, double y, boolean allowError) {
        double[] result = new double[2];
        if (srcCrs.equals("EPSG:4326") && dstCrs.equals("EPSG:3857")) {
            result = lonLat2WebMercator(x, y);
        } else if (srcCrs.equals("EPSG:3857") && dstCrs.equals("EPSG:4326")) {
            result = WebMercator2lonLat(x, y);
        } else {
            try {
                MathTransform transform = CRS.findMathTransform(CRS.decode(srcCrs), CRS.decode(dstCrs), allowError);
                Coordinate sourceLeftUpCoord = new Coordinate(x, y);
                Geometry srcPoint = geometryFactory.createPoint(sourceLeftUpCoord);
                Geometry dstPoint = JTS.transform(srcPoint, transform);

                result[0] = dstPoint.getCoordinate().getX();
                result[1] = dstPoint.getCoordinate().getY();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static Geometry crsTransform(String srcCrs, String dstCrs, Geometry geometrySource) {
        double[] result = new double[2];
        try {
            MathTransform transform = CRS.findMathTransform(CRS.decode(srcCrs,true),
                    CRS.decode(dstCrs,true), false);
            Geometry dstPoint = JTS.transform(geometrySource, transform);
            result[0] = dstPoint.getCoordinate().getX();
            result[1] = dstPoint.getCoordinate().getY();
            return dstPoint;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
//        double[] source = new double[]{geometrySource.getCoordinate().getX(),geometrySource.getCoordinate().getY()};
    }

    public static double[] crsTransform(String srcCrs, String dstCrs, double x, double y) {
        double[] result = new double[2];
        try {
            MathTransform transform = CRS.findMathTransform(CRS.decode(srcCrs,true),
                    CRS.decode(dstCrs,true), false);
            Coordinate sourceLeftUpCoord = new Coordinate(x, y);
            Geometry srcPoint = geometryFactory.createPoint(sourceLeftUpCoord);
            Geometry dstPoint = JTS.transform(srcPoint, transform);

            result[0] = dstPoint.getCoordinate().getX();
            result[1] = dstPoint.getCoordinate().getY();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
